﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using System.Xml.Linq;
using System.Security.AccessControl;

namespace TestBAT
{
    public class TestBATExecution
    {
        FileInfo fI;
        StreamWriter oDDF;
        List<FileNames> lstFilesCollection;
        System.Diagnostics.Process proc = null;
        public string ExecuteCoverage(string testContainer, string ConfigFile, string resultFile,string configName,string fileExtractPath)
        {
            string status = string.Empty;
            Assembly asm = Assembly.GetExecutingAssembly();
            string path = asm.Location.Substring(0, asm.Location.LastIndexOf("\\"));

            if (!Directory.Exists(fileExtractPath))
            {
                Directory.CreateDirectory(fileExtractPath);
            }

            if (File.Exists(resultFile))
            {
                File.Delete(resultFile);
            }
            
            fI = new FileInfo(fileExtractPath +  "\\CoverageExecution.bat");
            char[] chr= new char[] { ';'}; 
            string[] testContianerList = testContainer.Split(chr, StringSplitOptions.RemoveEmptyEntries);

            string a=string.Empty;
            foreach (string s in testContianerList)
            {
                string te = " /testcontainer:\"" + s + "\" ";
                 a = a + te;
            }

            oDDF = fI.CreateText();
            //oDDF.WriteLine("\"C:\\Program Files\\Microsoft Visual Studio 9.0\\Common7\\IDE\\MSTest.exe\" /testcontainer:\"" + testContainer + "\" /runconfig:\"" + ConfigFile + "\" /resultsfile:\"" + resultFile + "\"");            
            oDDF.WriteLine("\"C:\\Program Files\\Microsoft Visual Studio 9.0\\Common7\\IDE\\MSTest.exe\"" + a + "/runconfig:\"" + ConfigFile + "\" /resultsfile:\"" + resultFile + "\"");            
            oDDF.Close();


            path = asm.Location.Substring(0, asm.Location.LastIndexOf("\\"));
            fI = new FileInfo(fileExtractPath +  "\\CoverageBuild.bat");
            oDDF = fI.CreateText();
            oDDF.WriteLine("\"c:\\Windows\\Microsoft.NET\\Framework\\v3.5\\MSBuild.exe\" \"" + fileExtractPath + "\\build.proj\" ");
            oDDF.Close();

            // Build.proj updates will happen here.

            Assembly asmbly = Assembly.GetExecutingAssembly();
            TextReader fxcpStream = new StreamReader(asmbly.GetManifestResourceStream("TestBAT.Targets.build.proj"));
            
            XDocument doc = XDocument.Load(fxcpStream);
            XNamespace defaultns = "http://schemas.microsoft.com/developer/msbuild/2003";
            XElement ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "TestContainerFullPath");
            ele.Value = testContainer;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "ConfigFileFullPath");
            ele.Value = ConfigFile;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "ConfigName");
            ele.Value = configName;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "ResultFileFullPath");
            ele.Value = resultFile;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "ServerName");
            ele.Value = System.Environment.MachineName;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "EnableNunit");
            ele.Value = "false";

            string comDir = resultFile.Substring(0, resultFile.LastIndexOf("\\") + 1);
            if (!Directory.Exists(comDir))
            {
                //Directory.Delete(comDir,true);
                Directory.CreateDirectory(comDir);
            }            
            comDir = comDir + configName;

            if (Directory.Exists(comDir))
            {
                Directory.Delete(comDir,true);
            }

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "CoverageFileFullPath");
            ele.Value = comDir + @"\In\" + System.Environment.MachineName + @"\data.coverage";


            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "SymbolDir");
            ele.Value = comDir + @"\Out";
            
            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "OutputDir");
            ele.Value = comDir + @"\In\" + System.Environment.MachineName;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "FileExtractionPath");
            ele.Value = fileExtractPath;


            doc.Save(fileExtractPath + "\\build.proj");

            exec(fileExtractPath);

            //history of Coverage XML file to particular location
            //----------------------
            //string frmFile = comDir + @"\In\" + System.Environment.MachineName + @"\data.xml";            
            //string destFile = string.Format("c:\\temp\\data_{0:yyyy-MM-dd_hh-mm-ss-tt}.xml",DateTime.Now);

            //if (File.Exists(frmFile))
            //{
            //    File.Copy(frmFile, destFile);
            
            //}
            //-----------------------

            while (!proc.HasExited)
            {
                System.Threading.Thread.Sleep(1000);

            }
            string fileReturn;
            if (File.Exists(comDir + @"\In\" + System.Environment.MachineName + @"\data.xml"))
            {
                fileReturn = comDir + @"\In\" + System.Environment.MachineName + @"\data.xml";
            }
            else

            {
                fileReturn=string.Empty;
            }

            return fileReturn;

        }

        private void exec(string path)
        {

            string strFilePath = path  + "\\CoverageBuild.bat";

            // Create the ProcessInfo object
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo("cmd.exe");
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.UseShellExecute = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardInput = true;
            psi.RedirectStandardError = true;
            psi.WorkingDirectory = path;

        // Start the process
        proc = System.Diagnostics.Process.Start(psi);

        // Open the batch file for reading
        System.IO.StreamReader strm = System.IO.File.OpenText(strFilePath); 

        // Attach the output for reading
            System.IO.StreamReader sOut = proc.StandardOutput;

        // Attach the in for writing
        System.IO.StreamWriter sIn = proc.StandardInput;


        // Write each line of the batch file to standard input
                while(strm.Peek() != -1)
                    {
                        sIn.WriteLine(strm.ReadLine());
                    }

                strm.Close();

            // Exit CMD.EXE
            string stEchoFmt = "# {0} run successfully. Exiting";

            sIn.WriteLine(String.Format(stEchoFmt, strFilePath));
            sIn.WriteLine("EXIT");

            // Close the process
            //proc.Close();
        
            // Close the io Streams;
            sIn.Close();
            sOut.Close();

            
        }        

        private void SetDirSecurity(string directoryName)
        {
            DirectoryInfo dInfo = new DirectoryInfo(directoryName);

            DirectorySecurity dSecurity = dInfo.GetAccessControl();

            // Add the FileSystemAccessRule to the security settings. 
            dSecurity.AddAccessRule(new FileSystemAccessRule("EveryOne",FileSystemRights.FullControl,AccessControlType.Allow));            
            // Set the new access settings.
            dInfo.SetAccessControl(dSecurity);
        }

        public List<FileNames> GetCoverageSource(string srcPath)

        {

            lstFilesCollection = new List<FileNames>();

            FileNames flns = null;

            string strFilter = "*.xml";

            DirectoryInfo dInfo = new DirectoryInfo(srcPath);

            FileInfo[] fInfo;

            fInfo = dInfo.GetFiles(strFilter);

            foreach (FileInfo flInfo in fInfo)

            {

                flns = new FileNames();

                flns.FileName = flInfo.Name;

                lstFilesCollection.Add(flns);

            }

            return lstFilesCollection;

        }


        public void MSCovScriptCreation(string parentFolder, string CoverageOutputFile, string TestBinary,string NunitExe )
        {
            fI = new FileInfo(parentFolder + "\\mscodecov.bat");
            oDDF = fI.CreateText();
            oDDF.WriteLine("\"c:\\Program Files\\Microsoft Visual Studio 9.0\\Team Tools\\Performance Tools\\VSPerfCmd.exe \"  /start:coverage /output:" +  parentFolder + "\\" + CoverageOutputFile);
            oDDF.WriteLine("\"" + NunitExe + "\" " + TestBinary);
            oDDF.WriteLine("\"c:\\Program Files\\Microsoft Visual Studio 9.0\\Team Tools\\Performance Tools\\VSPerfCmd.exe \" /shutdown");
            oDDF.Close();
        }

        public string ExecuteNunitCoverage(string NunitExePAth, string testContainer, string AssmeblyList, string resultFile, string fileExtractPath, string dllLocation)
            {            
            string fileName, destFile; 

            if (!Directory.Exists(fileExtractPath))
            {
                Directory.CreateDirectory(fileExtractPath);                
            }

            if (Directory.Exists(fileExtractPath + "\\Content"))
            {
                Directory.Delete(fileExtractPath + "\\Content",true);
                Directory.CreateDirectory(fileExtractPath + "\\Content");
            }
            else
            {
                Directory.CreateDirectory(fileExtractPath + "\\Content");
            }

 

            if (File.Exists(fileExtractPath + "\\" + resultFile))
            {
                File.Delete(fileExtractPath + "\\" + resultFile);
            }

            if (System.IO.Directory.Exists(dllLocation))
            {
                string[] files = System.IO.Directory.GetFiles(dllLocation);

                // Copy the files and overwrite destination files if they already exist.
                foreach (string s in files)
                {
                    // Use static Path methods to extract only the file name from the path.
                    fileName = System.IO.Path.GetFileName(s);
                    destFile = System.IO.Path.Combine(fileExtractPath + "\\Content", fileName);
                    System.IO.File.Copy(s, destFile, true);
                }
            }
            else
            {
                Console.WriteLine("Source path does not exist!");
            }

            
            Assembly asmbly = Assembly.GetExecutingAssembly();
            TextReader fxcpStream = new StreamReader(asmbly.GetManifestResourceStream("TestBAT.Targets.build.proj"));

            XDocument doc = XDocument.Load(fxcpStream);
            XNamespace defaultns = "http://schemas.microsoft.com/developer/msbuild/2003";

            XElement ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "EnableNunit");
            ele.Value = "true";

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "NunitExePath");
            ele.Value = NunitExePAth;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "NunitTestAssembly");
            ele.Value = fileExtractPath + "\\Content\\" + testContainer;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "NunitAssemblyList");
            ele.Value = AssmeblyList;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "NunitCoverageOutput");
            ele.Value = resultFile;

            ele = doc.Root.Element(defaultns + "PropertyGroup").Element(defaultns + "NunitFileExtractionPath");
            ele.Value = fileExtractPath;

            ele = null;

            doc.Save(fileExtractPath + "\\build.proj");

            doc = null;

            fI = new FileInfo(fileExtractPath + "\\CoverageBuild.bat");
            oDDF = fI.CreateText();
            oDDF.WriteLine("\"c:\\Windows\\Microsoft.NET\\Framework\\v3.5\\MSBuild.exe\" \"" + fileExtractPath + "\\build.proj\" ");
            oDDF.Close();

            MSCovScriptCreation(fileExtractPath, resultFile, testContainer, NunitExePAth);

            exec(fileExtractPath);

            string rptfile = resultFile.Substring(0, resultFile.IndexOf('.'));
            string xmlfile = fileExtractPath + "\\" + rptfile + ".xml";
            //Wait until the xml file generaiton
            while (!File.Exists(xmlfile))
            {
                System.Threading.Thread.Sleep(1000);
            } 
            return xmlfile;
            
        }



    }

    public class FileNames
    {

        public string FileName { get; set; }

    }

 

    }




